package tests;

import java.util.ArrayList;

import junit.framework.TestCase;
import classes.Calculator;
import classes.Calculator.TokenType;

public class CalculatorTest extends TestCase {

	public String	e_inFix = "1 + 2 * 4 - 12 / 4";
	public String	e_postFix = "1 2 4 * + 12 4 / -";

	public void testCalculate() {
		try {
			double	value = Calculator.calculate(e_inFix);
			System.out.println("value = " + value);
			assertTrue(value==6d);
		} catch (Exception e) {
			fail(e.toString());
		}
		
	}

	public void testTokenizeWithBrackets() {
		
		try {
			ArrayList<String>	inFix = Calculator.tokenize("2 * ( 1 + 1 )");
			printTokens(inFix);
			
			assertTrue(inFix.size()==7);
			assertTrue(inFix.get(0).equals("2"));
			assertTrue(inFix.get(1).equals("*"));
			assertTrue(inFix.get(2).equals("("));
			assertTrue(inFix.get(3).equals("1"));
			assertTrue(inFix.get(4).equals("+"));
			assertTrue(inFix.get(5).equals("1"));
			assertTrue(inFix.get(6).equals(")"));
			
		} catch (Exception e) {
			fail(e.toString());
		}
		
		
	}
	
	public void testTokenize() {
		System.out.println("Part A");
		try {
			ArrayList<String>	inFix = Calculator.tokenize(e_inFix);
			printTokens(inFix);
			
			assertTrue(inFix.size()==9);
			assertTrue(inFix.get(0).equals("1"));
			assertTrue(inFix.get(1).equals("+"));
			assertTrue(inFix.get(2).equals("2"));
			assertTrue(inFix.get(3).equals("*"));
			assertTrue(inFix.get(4).equals("4"));
			assertTrue(inFix.get(5).equals("-"));
			assertTrue(inFix.get(6).equals("12"));
			assertTrue(inFix.get(7).equals("/"));
			assertTrue(inFix.get(8).equals("4"));
			
		} catch (Exception e) {
			fail(e.toString());
		}
	}

	public void testInfixToPostfixWithBrackets() {
		try {
			ArrayList<String>	inFix = null;
			ArrayList<String>	postFix = null;
			
			inFix = Calculator.tokenize("2 * ( 1 + 1 )");
			postFix = Calculator.infixToPostfix(inFix);

			System.out.println("===== postFix =====");
			printTokens(postFix);
			// e_postFix = "1 2 4 * + 12 4 / -";
						
			assertTrue(postFix.get(0).equals("2"));
			assertTrue(postFix.get(1).equals("1"));
			assertTrue(postFix.get(2).equals("1"));
			assertTrue(postFix.get(3).equals("+"));
			assertTrue(postFix.get(4).equals("*"));
			
		} catch (Exception e) {
			e.printStackTrace();
			fail(e.toString());
		}
	}
	
	public void testInfixToPostfix() {

		try {
			ArrayList<String>	inFix = null;
			ArrayList<String>	postFix = null;
			
			inFix = Calculator.tokenize(e_inFix);
			postFix = Calculator.infixToPostfix(inFix);

			System.out.println("===== postFix =====");
			printTokens(postFix);
			// e_postFix = "1 2 4 * + 12 4 / -";
						
			assertTrue(postFix.get(0).equals("1"));
			assertTrue(postFix.get(1).equals("2"));
			assertTrue(postFix.get(2).equals("4"));
			assertTrue(postFix.get(3).equals("*"));
			assertTrue(postFix.get(4).equals("+"));
			assertTrue(postFix.get(5).equals("12"));
			assertTrue(postFix.get(6).equals("4"));
			assertTrue(postFix.get(7).equals("/"));
			assertTrue(postFix.get(8).equals("-"));
			
		} catch (Exception e) {
			fail(e.toString());
		}
		
	}

	public void testEvaluatePostfix() {
		try {
			ArrayList<String>	inFix = null;
			ArrayList<String>	postFix = null;
			
			inFix = Calculator.tokenize(e_inFix);		// We know this works
			postFix = Calculator.infixToPostfix(inFix);	// We know this works
			
			printTokens(postFix);
			double value = Calculator.evaluatePostfix(postFix);
			
			System.out.println("value == " + value);
			assertTrue(value==6d);
			
			
		} catch (Exception e) {
			System.err.println(e.toString());
			e.printStackTrace();
			fail(e.toString());
		}
	}

	public void testGetTokenType() {
		assertTrue(Calculator.getTokenType("+") == TokenType.addition);
		assertTrue(Calculator.getTokenType("-") == TokenType.subtract);
		assertTrue(Calculator.getTokenType("/") == TokenType.divide);
		assertTrue(Calculator.getTokenType("*") == TokenType.multiply);
		assertTrue(Calculator.getTokenType("(") == TokenType.open);
		assertTrue(Calculator.getTokenType(")") == TokenType.close);
		assertTrue(Calculator.getTokenType("%") == TokenType.modulus);
		
		assertTrue(Calculator.getTokenType("0") == TokenType.number);
		assertTrue(Calculator.getTokenType("1") == TokenType.number);
		assertTrue(Calculator.getTokenType("2") == TokenType.number);
		assertTrue(Calculator.getTokenType("3") == TokenType.number);
		assertTrue(Calculator.getTokenType("4") == TokenType.number);
		assertTrue(Calculator.getTokenType("5") == TokenType.number);
		assertTrue(Calculator.getTokenType("6") == TokenType.number);
		assertTrue(Calculator.getTokenType("7") == TokenType.number);
		assertTrue(Calculator.getTokenType("8") == TokenType.number);
		assertTrue(Calculator.getTokenType("9") == TokenType.number);
		assertTrue(Calculator.getTokenType("0.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("1.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("2.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("3.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("4.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("5.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("6.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("7.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("8.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("9.0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType(".0") == TokenType.number);
		assertTrue(Calculator.getTokenType("01.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("11.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("21.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("31.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("41.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("51.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("61.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("71.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("81.0") == TokenType.number);
		assertTrue(Calculator.getTokenType("91.0") == TokenType.number);
		
	}
	
	public void printTokens(ArrayList<String> A) {
		Calculator.printTokens(A);
	}

	
}
